package cz.mff.cuni.dpp.liboptions;

import org.junit.Test;

/**
 * Ukázka použití, která je použita v uživatelské dokumentaci. Ukazuje použití
 * všech Typů Option, ukazuje jak reagovat na to, že je volba osbažena i na
 * chyby ve vstupu.
 * <p>
 * Aby se toho na malém prostoru dalo ukázat co nejvíc, není zde konzistence v
 * použití. (Reálně by uživatel volil, mezi zpracováním callbackem či testem na
 * přítomnost iption ve vstupu)
 * 
 * 
 */
public class UsageTemplateTest {

	private static final String SWITCH_PLUS = "plus";
	private static final String SWITCH_MINUS = "minus";

	private static int number;
	private static String label = "RESULT:";

	/**
	 * Pro cisla od 10 do 20 prida nebo ubere jednicku a vypise vysledek
	 */
	public static void main(String[] args) {
		Options options = new Options();
		// Povinna volba cisla v rozmezi 10-20, pritmomnost vyvola callback
		IntegerOption numberOption = new IntegerOption.Builder("number", "NUMBER-OF-SMTHNG", true)
				.addAlias("n").setLowerBound(10).setUpperBound(20)
				.setCallback(new OptionCallbackAdapter<Integer>() {
					@Override
					public void handleOptionValue(Integer parameter) {
						number = parameter;
					}
				}).buildOption();
		// Povinna volba ze dvou prvku, na velikosti nezalezi
		EnumOption chooseOption = new EnumOption.Builder("operation", "OPERATION")
				.setObligatory(true).addAlias("o").addAllowedValues(SWITCH_PLUS, SWITCH_MINUS)
				.setCaseSensitive(false).buildOption();
		// Nepovinna volba se stringovou hodnotou
		StringOption labelOption = new StringOption.Builder("label", "LABEL").addAlias("l")
				.buildOption();
		// Volitelny prepinac pro vzpsani helpu, u builderu neni vyuzit fluid
		// interface
		SwitchOption.Builder helpBuilder = new SwitchOption.Builder("help");
		helpBuilder.addAlias("h");
		helpBuilder
				.setDescription("Je sranda, ze jenom parametr help ma popisek, takze se stejne nic nedozvite");
		SwitchOption helpOption = helpBuilder.buildOption();

		// Vsechny optionz musime "zapojit", pokud by doslo ke konfliktu nayvu
		// nebo aliasu dosatnu vyjimku!
		options.addOptionDefinition(numberOption);
		options.addOptionDefinition(labelOption);
		options.addOptionDefinition(chooseOption);
		options.addOptionDefinition(helpOption);

		// Zpracovani vstupu od uziavtele
		Result result = options.process(args);

		// Pokud uzovatel zapomel neco zadat, nebo chce napovedu
		if (result.hasErrors() || result.isPresent(helpOption)) {
			options.printHelp();

			// reakce na specifikou chybu
			if (result.getErrors().getOutOfRange().containsKey(numberOption)) {
				// Spatna hodnota je vzdy String
				String badValue = result.getErrors().getOutOfRange().get(numberOption);
				System.out.println("umim pocitat pouze do dvou ne do " + badValue);
			}
		} else {
			// vyvolame callback
			result.callCallbacks(false);

			// Takto se muze pristoupit na hodnoty
			if (result.isPresent(labelOption)) {
				label = result.getValue(labelOption);
			}

			// vime ze nebyl error a tedy chooseOption musi byt pritomen
			String operation = result.getValue(chooseOption);
			if (SWITCH_MINUS.equalsIgnoreCase(operation)) {
				number--;
			} else if (SWITCH_PLUS.equalsIgnoreCase(operation)) {
				number++;
			} else {
				// sem se nikdy kod nedostane
			}

			System.out.println(label + number);

			// Pokud bych potreboval sahat na argumety
			result.getArguments();
		}

	}

	@Test
	public void possitiveTest() {
		UsageTemplateTest.main(new String[] { "-n", "10", "--operation=plus" });
		UsageTemplateTest.main(new String[] { "-n", "15", "-o", "MiNUs" });
	}

	@Test
	public void negativeTest() {
		UsageTemplateTest.main(new String[] { "-n", "32", "--operation=plus" });
		UsageTemplateTest.main(new String[] {});
		UsageTemplateTest.main(new String[] { "--help" });
		UsageTemplateTest.main(new String[] { "-n", "10", "--operation=plus", "-blah" });
	}
}
